{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2EFDA196FD44477C8998AF4A4AF6BC9D",
    "jupyter": {},
    "mdEditEnable": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "# Python机器学习Kaggle案例实战（第21期） 第5课书面作业\n",
    "学号：113778 \n",
    "1. 尝试编写程序，实现使用不同的哈希算法比较图片相似度（图片的处理可以使用python的PIL库）\n",
    "2. 尝试编写程序，实现通过直方图交叉核算法来比较图片相似度\n",
    "\n",
    "## 作业1\n",
    "尝试编写程序，实现使用不同的哈希算法比较图片相似度（图片的处理可以使用python的PIL库）  \n",
    "这里没有采用pil库，使用了opencv的库。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "id": "2299E10AC1F942708DAD64090B0A6BAE",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "id": "994D9D325C404FE09B8F6F45055A18F0",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "#均值哈希算法\n",
    "def aHash(imgfile):\n",
    "    img=cv2.imread(imgfile)\n",
    "    #缩放为8*8\n",
    "    img=cv2.resize(img,(8,8),interpolation=cv2.INTER_CUBIC)\n",
    "    #转换为灰度图\n",
    "    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)\n",
    "    #s为像素和初值为0，hash_str为hash值初值为''\n",
    "    s=0\n",
    "    hash_str=''\n",
    "    #遍历累加求像素和\n",
    "    for i in range(8):\n",
    "        for j in range(8):\n",
    "            s=s+gray[i,j]\n",
    "    #求平均灰度\n",
    "    avg=s/64\n",
    "    #灰度大于平均值为1相反为0生成图片的hash值\n",
    "    for i in range(8):\n",
    "        for j in range(8):\n",
    "            if gray[i,j]>avg:\n",
    "                hash_str=hash_str+'1'\n",
    "            else:\n",
    "                hash_str=hash_str+'0'\n",
    "    return hash_str"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "B01FCCDD69794971895854C1A44B76F7",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "#差值哈希算法\n",
    "def dHash(imgfile):\n",
    "    img=cv2.imread(imgfile)\n",
    "    #缩放8*8\n",
    "    img=cv2.resize(img,(9,8),interpolation=cv2.INTER_CUBIC)\n",
    "    #转换灰度图\n",
    "    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)\n",
    "    hash_str=''\n",
    "    #每行前一个像素大于后一个像素为1，相反为0，生成哈希\n",
    "    for i in range(8):\n",
    "        for j in range(8):\n",
    "            if gray[i,j]>gray[i,j+1]:\n",
    "                hash_str=hash_str+'1'\n",
    "            else:\n",
    "                hash_str=hash_str+'0'\n",
    "    return hash_str"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "01544BDEAF8B47749C666C807D418404",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "#Hash值对比\n",
    "def cmpHash(hash1,hash2):\n",
    "    n=0\n",
    "#hash长度不同则返回-1代表传参出错\n",
    "    if len(hash1)!=len(hash2):\n",
    "        return -1\n",
    "#遍历判断\n",
    "    for i in range(len(hash1)):\n",
    "#不相等则n计数+1，n最终为相似度\n",
    "        if hash1[i]!=hash2[i]:\n",
    "            n=n+1\n",
    "    return 1 - n / 64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "72B4E4F76E1A4DA28DCD731B41D4C093",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "#感知哈希算法\n",
    "def pHash(imgfile):\n",
    "    #统一将图片尺寸缩放为32*32，一共得到了1024个像素点。\n",
    "    img_list=[]\n",
    "    #加载并调整图片为32x32灰度图片\n",
    "    img=cv2.imread(imgfile)\n",
    "    img=cv2.resize(img,(32,32),interpolation=cv2.INTER_CUBIC)\n",
    "    #转换为灰度图\n",
    "    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)\n",
    "    #计算32x32数据矩阵的离散余弦变换后对应的32x32数据矩阵\n",
    "    #创建二维列表\n",
    "    h, w = 32,32\n",
    "    vis0 = np.zeros((h,w), np.float32)\n",
    "    vis0[:h,:w] = gray #填充数据\n",
    " \n",
    "    #二维Dct变换\n",
    "    vis1 = cv2.dct(cv2.dct(vis0))\n",
    "    #cv.SaveImage('a.jpg',cv.fromarray(vis0)) #保存图片\n",
    "    #vis1.resize(32,32)\n",
    "    vis2=vis1[:8,:8]\n",
    "\n",
    "    #把二维list变成一维list\n",
    "    img_list=vis2.flatten()\n",
    " \n",
    " \n",
    "    #计算均值\n",
    "    avg = sum(img_list)*1./len(img_list)\n",
    "    avg_list = ['0' if i>avg else '1' for i in img_list]\n",
    "    return ''.join(avg_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "71108937C4FB47D99C45D132896F2A23",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def hammingDist(s1, s2):\n",
    "#assert len(s1) == len(s2)\n",
    "    return sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "B0B1DA2C930F488280C193EBBBD6BF0F",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img1.jpg:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/B0B1DA2C930F488280C193EBBBD6BF0F/qxcg6mce5v.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img2.jpg:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/B0B1DA2C930F488280C193EBBBD6BF0F/qxcg6nrm76.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img3.jpg:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/B0B1DA2C930F488280C193EBBBD6BF0F/qxcg6nhdi6.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline\n",
    "img1 = cv2.imread('img1.jpg')\n",
    "plt.imshow(img1)\n",
    "print('img1.jpg:')\n",
    "plt.show()\n",
    "\n",
    "img2 = cv2.imread('img2.jpg')\n",
    "plt.imshow(img2)\n",
    "print('img2.jpg:')\n",
    "plt.show()\n",
    "\n",
    "img3 = cv2.imread('img3.jpg')\n",
    "plt.imshow(img3)\n",
    "print('img3.jpg:')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "id": "B605A02BFEBF4E138ED3527802675A11",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1均值哈希： 1111111111111111111111111111111111011011110001111111111111011111\n",
      "Img2均值哈希： 1111111111111111111111111111111111011011110001111111111111011111\n",
      "两图在均值哈希下的汉明距离： 15\n"
     ]
    }
   ],
   "source": [
    "hash1 = aHash(\"img1.jpg\")\n",
    "print('Img1均值哈希：', hash1)\n",
    "hash2 = aHash(\"img2.jpg\")\n",
    "print('Img2均值哈希：', hash1)\n",
    "print('两图在均值哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "id": "4739B1BD0D2F466E869DD3ED569EECF2",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1差值哈希： 0001000001000000000000000100000001101000010000000010000000100100\n",
      "Img2差值哈希： 0001000001000000000000000100000001101000010000000010000000100100\n",
      "两图在差值哈希下的汉明距离： 21\n"
     ]
    }
   ],
   "source": [
    "hash1 = dHash(\"img1.jpg\")\n",
    "print('Img1差值哈希：', hash1)\n",
    "hash2 = dHash(\"img2.jpg\")\n",
    "print('Img2差值哈希：', hash1)\n",
    "print('两图在差值哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "id": "EC3DC4C7AB9E4AD19F5CD033C689CE76",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1感知哈希： 1111111110000000100000001000000010000000100000011000000010000001\n",
      "Img2感知哈希： 1111111110000000100000001000000010000000100000011000000010000001\n",
      "两图在感知哈希下的汉明距离： 4\n"
     ]
    }
   ],
   "source": [
    "hash1 = pHash(\"img1.jpg\")\n",
    "print('Img1感知哈希：', hash1)\n",
    "hash2 = pHash(\"img2.jpg\")\n",
    "print('Img2感知哈希：', hash1)\n",
    "print('两图在感知哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "id": "305F805CEFB849F88CDF7818C6CB5DE8",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1均值哈希： 1111111111111111111111111111111111011011110001111111111111011111\n",
      "Img3均值哈希： 1111111111111111111111111111111111011011110001111111111111011111\n",
      "两图在均值哈希下的汉明距离： 30\n"
     ]
    }
   ],
   "source": [
    "hash1 = aHash(\"img1.jpg\")\n",
    "print('Img1均值哈希：', hash1)\n",
    "hash2 = aHash(\"img3.jpg\")\n",
    "print('Img3均值哈希：', hash1)\n",
    "print('两图在均值哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "id": "5A25EBBD4F5E46969622217A27224B64",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1差值哈希： 0001000001000000000000000100000001101000010000000010000000100100\n",
      "Img3差值哈希： 0001000001000000000000000100000001101000010000000010000000100100\n",
      "两图在差值哈希下的汉明距离： 28\n"
     ]
    }
   ],
   "source": [
    "hash1 = dHash(\"img1.jpg\")\n",
    "print('Img1差值哈希：', hash1)\n",
    "hash2 = dHash(\"img3.jpg\")\n",
    "print('Img3差值哈希：', hash1)\n",
    "print('两图在差值哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "id": "13EE6D01D0DE4956A7C425A6289DD1A6",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Img1感知哈希： 1111111110000000100000001000000010000000100000011000000010000001\n",
      "Img3感知哈希： 1111111110000000100000001000000010000000100000011000000010000001\n",
      "两图在感知哈希下的汉明距离： 11\n"
     ]
    }
   ],
   "source": [
    "hash1 = pHash(\"img1.jpg\")\n",
    "print('Img1感知哈希：', hash1)\n",
    "hash2 = pHash(\"img3.jpg\")\n",
    "print('Img3感知哈希：', hash1)\n",
    "print('两图在感知哈希下的汉明距离：',hammingDist(hash1, hash2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8EB031F50F01496C90BE415C30133360",
    "jupyter": {},
    "mdEditEnable": false,
    "notebookId": "610a61d5fe7277001769c596",
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## 作业2\n",
    "尝试编写程序，实现通过直方图交叉核算法来比较图片相似度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "928DF97B05444DA7B92202EDD903840A",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import time\n",
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "D579496C8A68413E938991E60B17624D",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img1.jpg:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/D579496C8A68413E938991E60B17624D/qxdbovms43.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "img1=cv2.imread('img1.jpg')\n",
    "plt.imshow(img1)\n",
    "print('img1.jpg:')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "2DA373CA1C684B2D8198F833F6CDF592",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/2DA373CA1C684B2D8198F833F6CDF592/qxdbs2cpbz.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "img1=cv2.resize(img1,(64,64),interpolation=cv2.INTER_CUBIC)\n",
    "gray1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)\n",
    "plt.imshow(gray1,plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "519AC6EFFADE4A7A87FC99A5C7E64573",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img2.jpg:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/519AC6EFFADE4A7A87FC99A5C7E64573/qxdbsxairm.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "img2=cv2.imread('img2.jpg')\n",
    "plt.imshow(img2)\n",
    "print('img2.jpg:')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "A4B85BAA4E56471CB895EAE846D17926",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.kesci.com/upload/rt/A4B85BAA4E56471CB895EAE846D17926/qxdbtqwxus.png\">"
      ],
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "img2=cv2.resize(img2,(64,64),interpolation=cv2.INTER_CUBIC)\n",
    "gray2=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)\n",
    "plt.imshow(gray2,plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "A94B4D78F17144989BCBD9D90A84EC77",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def l_func(Hx,Hy):\n",
    "    lx=Hx.shape[0]\n",
    "    ly=Hy.shape[0]\n",
    "    if lx!=ly:\n",
    "        print('Two histogram not in same shape!')\n",
    "        return -1\n",
    "    a=0\n",
    "    for i in range(lx):\n",
    "        a+=min(Hx[i][0],Hy[i][0])\n",
    "    return a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "id": "113B51A2AE8E4C70A41E7C8457C2F4FB",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "两图的直方图交叉核： 331.6796875\n"
     ]
    }
   ],
   "source": [
    "biniter=[256,128,64,32,16,8,4,2]\n",
    "m=0\n",
    "Li_1=0\n",
    "k=0\n",
    "for i in biniter:\n",
    "    hist1=cv2.calcHist([gray1],[0],None,[i],[0,255])\n",
    "    hist2=cv2.calcHist([gray2],[0],None,[i],[0,255])\n",
    "    w=2**m\n",
    "    m+=1\n",
    "    Li=l_func(hist1,hist2)\n",
    "    Ni=Li-Li_1\n",
    "    Li_1=Li\n",
    "    k+=(1./w)*Ni\n",
    "print('两图的直方图交叉核：',k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "AA7D9840E8374699BC94610F32EE3EC5",
    "jupyter": {},
    "notebookId": "610a61d5fe7277001769c596",
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
